package implementation1.app.commands;

import exceptions.CommandErrorFromUserException;
import exceptions.CommandException;
import exceptions.StreamEOFException;
import exceptions.StreamException;
import implementation1.app.Global;
import implementation1.app.streams.AccessAttributes;
import implementation1.app.streams.FileStream;
import implementation1.data.states.RunningStatus;
import implementation1.data.states.TerminatedStatus;
import implementation1.data.states.WaitingStatus;
import interfaces.app.IProcess;
import interfaces.app.IStream;
import interfaces.data.IHandle;

import java.io.File;
import java.util.ArrayList;

/**
 * Class for handle command "cat" for reading text file.
 * Created: 15.10.11
 *
 * @author Jan Svab
 */
public class Cat extends Command
{
    /**
     * Default constructor.
     *
     * @param parent parent process over which is command processed
     * @param handle parameters of command
     */
    public Cat(IProcess parent, IHandle handle)
    {
        super(parent, handle);
    }


    /**
     * Main method for processing of command.
     *
     * @param args arguments of command
     * @throws CommandException Thrown if occurs error during processing of the command.
     */
    @Override
    public void mainCommand(String[] args) throws CommandException
    {
        if (handle.getOut() == null)
        {
            throw new CommandException(bundle.getString("error.outputStream.empty"));
        }

        IStream inStream = null;
        IStream outStream = handle.getOut();

        //cat has as input stream from handle
        if (args == null || args.length == 0)
        {
            inStream = handle.getIn();
        }
        else if (args.length == 1)
        {
            //checking if file exist
            File file = Global.getFileWithAbsPath(handle.getActualPath(), args[0]);

            if (!file.exists() || !file.isFile())
            {
                throw new CommandErrorFromUserException(bundle.getString("error.file.noExist"));
            }

            //creating and opening of the stream fro reading
            inStream = new FileStream(file.getAbsolutePath());
        }
        else
        {
            throw new CommandErrorFromUserException(bundle.getString("error.arguments.wrongCount"));
        }

        try
        {
            outStream.open(AccessAttributes.WRITE);
            openedStreamsOfProcess.add(outStream);
            inStream.open(AccessAttributes.READ);
            openedStreamsOfProcess.add(inStream);

            ArrayList<String> buffer = new ArrayList<String>();

            //reading of the file
            while (true)
            {
                String s = null;
                try
                {
                    this.status = new WaitingStatus();
                    s = inStream.readLine();
                } catch (StreamEOFException e)
                {
                    break;  //end of file
                } finally
                {
                    this.status = new RunningStatus();
                }

                if (Thread.interrupted()) //in other process was created request on terminate this process
                {
                    status = new TerminatedStatus();
                    break;
                }

                if (hasEndStatus()) //thread should quit
                {
                    break;
                }

                buffer.add(s);
            }

            for (String line : buffer)
            {
                outStream.writeLine(line);
            }
        } catch (StreamException e)
        {
            throw new CommandException(e.getMessage());
        } finally
        {
            Global.closeStreamQuietly(inStream);
            Global.closeStreamQuietly(outStream);

            openedStreamsOfProcess.remove(inStream);
            openedStreamsOfProcess.remove(outStream);
        }
    }

    @Override
    public String toString()
    {
        return "cat";
    }
}
